#include "TuioDemo.h"
#include "Message.hxx"
#include <string.h>
#include <math.h>

#if defined(__WIN32__) || defined(WIN32)
#include <windows.h>
#endif

#ifdef __APPLE__
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#endif

TuioDemo::TuioDemo(TuioClient * client):tuioClient(client){
#ifndef __MACOSX__
    int argc = 1;
    char **argv = (char**)malloc(sizeof(char*));
    argv[0] = (char*)malloc(sizeof(char)*3);
    argv[0][0] = '\0';
	glutInit(&argc,argv);
#endif

	map_x=0;
	map_y=0;
	map_a=0;
	map_z=1;

	dit1_id=-1;
	dit1_s=-1;
	dit1_x=-1;
	dit1_y=-1;
	
	dit2_id=-1;
	dit2_s=-1;
	dit2_x=-1;
	dit2_y=-1;
	
	xi=-1.0f;
	yi=-1.0f;
	xii=-1.0f;
	yii=-1.0f;
	
	incxf=0.0f;
	incyf=0.0f;
	incaf=0.0f;
	inczf=1.0f;
	
	volume=0;
	
	tp1x=0.0f;
	tp1y=0.0f;
	tp2x=1.0f;
	tp2y=1.0f;
}


void TuioDemo::multMatrix(double a[16], double b[16]){
	double aux[16];
	
	// Fila 1
	aux[0]=a[0]*b[0]+a[1]*b[4]+a[2]*b[8]+a[3]*b[12];
	aux[1]=a[0]*b[1]+a[1]*b[5]+a[2]*b[9]+a[3]*b[13];
	aux[2]=a[0]*b[2]+a[1]*b[6]+a[2]*b[10]+a[3]*b[14];
	aux[3]=a[0]*b[3]+a[1]*b[7]+a[2]*b[11]+a[3]*b[15];
	
	// Fila 2
	aux[4]=a[4]*b[0]+a[5]*b[4]+a[6]*b[8]+a[7]*b[12];
	aux[5]=a[4]*b[1]+a[5]*b[5]+a[6]*b[9]+a[7]*b[13];
	aux[6]=a[4]*b[2]+a[5]*b[6]+a[6]*b[10]+a[7]*b[14];
	aux[7]=a[4]*b[3]+a[5]*b[7]+a[6]*b[11]+a[7]*b[15];
	
	// Fila 3
	aux[8]=a[8]*b[0]+a[9]*b[4]+a[10]*b[8]+a[11]*b[12];
	aux[9]=a[8]*b[1]+a[9]*b[5]+a[10]*b[9]+a[11]*b[13];
	aux[10]=a[8]*b[2]+a[9]*b[6]+a[10]*b[10]+a[11]*b[14];
	aux[11]=a[8]*b[3]+a[9]*b[7]+a[10]*b[11]+a[11]*b[15];
	
	// Fila 4
	aux[12]=a[12]*b[0]+a[13]*b[4]+a[14]*b[8]+a[15]*b[12];
	aux[13]=a[12]*b[1]+a[13]*b[5]+a[14]*b[9]+a[15]*b[13];
	aux[14]=a[12]*b[2]+a[13]*b[6]+a[14]*b[10]+a[15]*b[14];
	aux[15]=a[12]*b[3]+a[13]*b[7]+a[14]*b[11]+a[15]*b[15];
	
	// Copiem resultat a primera matriu
	for(int i=0; i<16; i++){
		a[i]=aux[i];
	}
}


void TuioDemo::computeMatrix(){
	double tArray[16];//,oArray[16];
	
	// Load Identity on tArray
	for (int i=0;i<4;i++){
		for (int j=0;j<4;j++){	
			if (i==j){tArray[(i*4)+j]=1.0f;}else{tArray[(i*4)+j]=0.0f;}
		}
	}
		
	// Translation x, y
	for (int i=0;i<4;i++){
		for (int j=0;j<4;j++){	
			if (i==j){tArray[(i*4)+j]=1.0f;}else{tArray[(i*4)+j]=0.0f;}
		}
	}
	tArray[12]=(double)incxf;
	tArray[13]=(double)incyf;
	multMatrix(modelview, tArray); // Apply
	
	// Translation -d
	for (int i=0;i<4;i++){
		for (int j=0;j<4;j++){	
			if (i==j){tArray[(i*4)+j]=1.0f;}else{tArray[(i*4)+j]=0.0f;}
		}
	}
	tArray[12]=-((double)dit1_x);
	tArray[13]=-((double)dit1_y);	 
	multMatrix(modelview, tArray); // Apply

	// Scaling 
	for (int i=0;i<16;i++){
		tArray[i]=0.0f;
	}
	tArray[0]=(double)inczf;
	tArray[5]=(double)inczf;
	tArray[10]=1.0f;
	tArray[15]=1.0f;	
	multMatrix(modelview, tArray); // Apply 
	
	// Rotation
	for (int i=0;i<4;i++){
		for (int j=0;j<4;j++){	
			if (i==j){tArray[(i*4)+j]=1.0f;}else{tArray[(i*4)+j]=0.0f;}
		}
	}
	tArray[0]=(double)cos(incaf);
	tArray[1]=(double)sin(incaf);
	tArray[4]=(double)-sin(incaf);
	tArray[5]=(double)cos(incaf);
	tArray[10]=1.0f;
	tArray[15]=1.0f;
	multMatrix(modelview, tArray); // Apply
	
	// Translation d
	for (int i=0;i<4;i++){
		for (int j=0;j<4;j++){	
			if (i==j){tArray[(i*4)+j]=1.0f;}else{tArray[(i*4)+j]=0.0f;}
		}
	}
	tArray[12]=(double)dit1_x;
	tArray[13]=(double)dit1_y;
	multMatrix(modelview, tArray); // Apply
	
	tp1x=modelview[12]; // Punt inferior esquerra transformat
	tp1y=modelview[13]; // Punt inferior esquerra transformat
	
	tp2x=tp1x+cos(map_a+M_PI/4)*map_z/0.707; // Punt superior dret transformat
	tp2y=tp1y+sin(map_a+M_PI/4)*map_z/0.707; // Punt superior dret transformat
	
}


void TuioDemo::detectaPais(){
	
	float dx = tp2x-tp1x;
	float dy = tp2y-tp1y;
	float dist1 = sqrtf(dx*dx+dy*dy);
	float angle1 = (float)(asin(dx/dist1)+M_PI/2);
	if (dy<0) angle1 = 2.0f*(float)M_PI-angle1;
	
	float dx2 = xi-tp1x;
	float dy2 = yi-tp1y;
	float dist2 = sqrtf(dx2*dx2+dy2*dy2);
	float angle2 = (float)(asin(dx2/dist2)+M_PI/2);
	if (dy2<0) angle2 = 2.0f*(float)M_PI-angle2;

	xii=dist2/dist1*cos((float)M_PI/4+(angle1-angle2));
	yii=dist2/dist1*sin((float)M_PI/4+(angle1-angle2));
	xii=xii/0.707;
	yii=yii/0.707;
	
	
	//Melodia para NorteAmerica
	if (xii>0 && xii<0.32 && yii>0.59 && yii<1){
		if (!Mix_Playing(1)){ 
			if(Mix_PlayChannel(1, sampleNA, 0)==-1) {
				printf("Mix_PlayChannel: %s\n",Mix_GetError());
			}
		}
	}
	//Melodia para Sudamerica
	else if (xii>0.18 && xii<0.42 && yii>0.17 && yii<0.55){
		if (!Mix_Playing(1)){ 
			if(Mix_PlayChannel(1, sampleSA, 0)==-1) {
				printf("Mix_PlayChannel: %s\n",Mix_GetError());
			}
		}
	}
	//Melodia para Africa
	else if (xii>0.5 && xii<0.84 && yii>0.33 && yii<0.69){
		if (!Mix_Playing(1)){ 
			if(Mix_PlayChannel(1, sampleAF, 0)==-1) {
				printf("Mix_PlayChannel: %s\n",Mix_GetError());
			}
		}
	}
	//Melodia para Europa
	else if (xii>0.53 && xii<1 && yii>0.7 && yii<1){
		if (!Mix_Playing(1)){ 
			if(Mix_PlayChannel(1, sampleEU, 0)==-1) {
				printf("Mix_PlayChannel: %s\n",Mix_GetError());
			}
		}
	}
	else {
		if (Mix_Playing(1)){ 
			// para la reproducció
			Mix_FadeOutChannel(1, 350);
		}
	}
 }


void TuioDemo::addTuioObject(TuioObject *tobj){
    sprintf(buff,
            "add obj %d (%d) %.2f %.2f %.2f",
            tobj->getFiducialID(),
            (int)tobj->getSessionID(),
            tobj->getX(),
            tobj->getY(),
            tobj->getAngle());
    Message::Info(std::string(buff));
	
	if (tobj->getFiducialID()==43){
		xi=tobj->getX();
		yi=tobj->getY();
	}
	
}


void TuioDemo::updateTuioObject(TuioObject *tobj){
    sprintf(buff,
            "set obj %d (%d) %.2f %.2f %.2f",
            tobj->getFiducialID(),
            (int)tobj->getSessionID(),
            tobj->getX(),
            tobj->getY(),
            tobj->getAngle());
    Message::Info(std::string(buff));
	
	// Mirem si és la figura que activa músiques (fid 43), i en aquest cas actualitzem la posicio xi,yi
	// (per saber sobre quin país està ho fem dins del bucle draw, que s'actualitza més ràpidament i permet fer loops)
	if (tobj->getFiducialID()==43){
		xi=tobj->getX();
		yi=tobj->getY();
		
		// Volume
		float volumef;
		volumef=128*(tobj->getAngle())/(2*M_PI);
		volume=(int)volumef;
		Mix_Volume(1,volume);
	}
}


void TuioDemo::removeTuioObject(TuioObject *tobj){
    sprintf(buff,
            "del obj %d (%d)",
            tobj->getFiducialID(),
            (int)tobj->getSessionID());
    Message::Info(std::string(buff));
	
	if (tobj->getFiducialID()==47){
		xi=-1;
		yi=-1;
		xii=-1;
		yii=-1;
	}
	
}


void TuioDemo::addTuioCursor(TuioCursor *tcur){
    sprintf(buff,
            "add cur %d (%d) %.2f %.2f",
            tcur->getFingerID(),
            (int)tcur->getSessionID(),
            tcur->getX(),
            tcur->getY());
    Message::Info(std::string(buff));
	
	// Guardar informació dels dits 1 i 2
	// ID, session, X i Y de cada dit
	if (dit1_id==-1){ // Assigna'l al dit 1
		dit1_id=tcur->getFingerID();
		dit1_s=tcur->getSessionID();
		dit1_x=tcur->getX();
		dit1_y=tcur->getY();
	} 
	else if((dit1_id!=-1)&&(dit2_id==-1)){ // Assigna'l al dit 2
		dit2_id=tcur->getFingerID();
		dit2_s=tcur->getSessionID();
		dit2_x=tcur->getX();
		dit2_y=tcur->getY();
	}
	else if((dit1_id!=-1)&&(dit2_id!=-1)){
		// No l'assignis enlloc
	}
}


void TuioDemo::computePosition(TuioCursor *tcur){
	float inc_x=0,inc_y=0;
	
	// Aplicar transformacions
	// 1. Translació al dit 1
	if (tcur->getFingerID()==dit1_id){
		inc_x=(tcur->getX()-dit1_x);
		inc_y=(tcur->getY()-dit1_y);
			
		incxf=inc_x; 
		incyf=inc_y; 
		
		map_x=map_x+inc_x;
		map_y=map_y+inc_y;
		
		dit1_x=tcur->getX();
		dit1_y=tcur->getY();
		
		// Mirar si existeix el dit2
		if (dit2_id!=-1){
			float dit2b_x=dit2_x+inc_x;
			float dit2b_y=dit2_y+inc_y;
			
			// Angle1 i dist entre (dit1_x,dit1_y) i (dit2b_x,dit2b_y)
			float dx = dit2b_x-dit1_x;
			float dy = dit2b_y-dit1_y;
			float dist1 = sqrtf(dx*dx+dy*dy);
			float angle1 = (float)(asin(dx/dist1)+M_PI/2);
			if (dy<0) angle1 = 2.0f*(float)M_PI-angle1;
			
			// Angle2 i dist entre (dit1_x,dit1_y) i (dit2_x,dit2_y) (actual, tcur->get...)	
			dx = dit2_x-dit1_x;
			dy = dit2_y-dit1_y;
			float dist2 = sqrtf(dx*dx+dy*dy);
			float angle2 = (float)(asin(dx/dist2)+M_PI/2);
			if (dy<0) angle2 = 2.0f*(float)M_PI-angle2;
			
			map_a=map_a-(angle2-angle1);
			map_z=map_z*(dist2/dist1);
			
			incaf=(angle1-angle2);
			inczf=inczf*(dist2/dist1);
		}
	}
	
	// 2. Actualitzem dit 1 (ID i sessió)
	if (tcur->getFingerID()==dit1_id){ // Update dit 1
		dit1_id=tcur->getFingerID();
		dit1_s=tcur->getSessionID();
	}
	
	// 3. Escalat i rotació: per fer quadrar el dit 2 segons el dit 1 (que ja és queda a on és)
	if (tcur->getFingerID()==dit2_id){		
		float dit2b_x=tcur->getX();
		float dit2b_y=tcur->getY();
		
		// Angle i dist entre (dit1_x,dit1_y) i (dit2b_x,dit2b_y)
		float dx = dit2b_x-dit1_x;
		float dy = dit2b_y-dit1_y;
		float dist1 = sqrtf(dx*dx+dy*dy);
		float angle1 = (float)(asin(dx/dist1)+M_PI/2);
		if (dy<0) angle1 = 2.0f*(float)M_PI-angle1;
		
		// Angle i dist entre (dit1_x,dit1_y) i (dit2_x,dit2_y) (actual, tcur->get...)	
		dx = dit2_x-dit1_x;
		dy = dit2_y-dit1_y;
		float dist2 = sqrtf(dx*dx+dy*dy);
		float angle2 = (float)(asin(dx/dist2)+M_PI/2);
		if (dy<0) angle2 = 2.0f*(float)M_PI-angle2;
		
		map_a=map_a+(angle2-angle1);
		map_z=map_z*(dist1/dist2);
		
		incaf=(angle2-angle1); 
		inczf=inczf*(dist1/dist2);
		
		// Update dit 2
		dit2_id=tcur->getFingerID();
		dit2_s=tcur->getSessionID();
		dit2_x=tcur->getX();
		dit2_y=tcur->getY();
	}
	
}


void TuioDemo::updateTuioCursor(TuioCursor *tcur){
    sprintf(buff,
            "set cur %d (%d) %.2f %.2f",
            tcur->getFingerID(),
            (int)tcur->getSessionID(),
            tcur->getX(),
            tcur->getY());
    Message::Info(std::string(buff));
	
	computePosition(tcur); // Calcula increments d'angle, escalar i posició a aplicar
	computeMatrix(); // Calcula matriu de transformació nova, la posició del punt inferior esquerra transformat i del punt superior dret
	// Posem a zero els increments (1 pel zoom) per evitar realimentacio i que es transformi a cada update
	incaf=0.0f;
	inczf=1.0f;
	incxf=0.0f;
	incyf=0.0f;
	
}


void TuioDemo::removeTuioCursor(TuioCursor *tcur){
    sprintf(buff,
            "del cur %d (%d)",
            tcur->getFingerID(),
            (int)tcur->getSessionID());
    Message::Info(std::string(buff));
	
	// Remove dit 1
	if ((tcur->getFingerID()==dit1_id)&&(tcur->getSessionID()==dit1_s)){ // Remove dit 1
		
		dit1_id=dit2_id;
		dit1_s=dit2_s;
		dit1_x=dit2_x;
		dit1_y=dit2_y;
		
		// Busquem si hi ha algun altre cursor que pugui fer de dit 2
		std::list<TuioCursor*> cursorList = tuioClient->getTuioCursors();
		for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
			if ((*tuioCursor)->getFingerID()!=dit2_id){
				dit2_id=(*tuioCursor)->getFingerID();
				dit2_s=(*tuioCursor)->getSessionID();
				dit2_x=(*tuioCursor)->getX();
				dit2_y=(*tuioCursor)->getY();
			}else{
				dit2_id=-1;
				dit2_s=-1;
				dit2_x=-1;
				dit2_y=-1;	
			}
		}
	}
	
	// Remove dit 2
	if ((tcur->getFingerID()==dit2_id)&&(tcur->getSessionID()==dit2_s)){ // Remove dit 2
		// Busquem si hi ha algun altre cursor que pugui fer de dit 2
		dit2_id=-1;
		dit2_s=-1;
		dit2_x=-1;
		dit2_y=-1;
	
		std::list<TuioCursor*> cursorList = tuioClient->getTuioCursors();
		for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
			if ((*tuioCursor)->getFingerID()!=dit1_id){
				dit2_id=(*tuioCursor)->getFingerID();
				dit2_s=(*tuioCursor)->getSessionID();
				dit2_x=(*tuioCursor)->getX();
				dit2_y=(*tuioCursor)->getY();
			}
		}
	}
}


void TuioDemo::refresh(long timestamp){}


void TuioDemo::drawMapaMundi(){
	// draw mapamundi
	glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, mapaID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glPushMatrix();
	glLoadMatrixd(modelview); // Carrega la transformació calculada i l'aplica
    glColor3ub(255,255,255);
	glBegin(GL_QUADS);glTexCoord2f(0,0);glVertex2f(0,0);glTexCoord2f(1,0);glVertex2f(1,0);glTexCoord2f(1,1);glVertex2f(1,1);glTexCoord2f(0,1);glVertex2f(0,1);glEnd();
    glPopMatrix();
	glDisable(GL_TEXTURE_2D);//Disable 2D texturing
	
	/*
	// Draw linia 0,0 1,1
	glColor3f(1.0, 0.0, 0.0);
	glPushMatrix();
	glLoadIdentity();
	glBegin(GL_LINES);
	glVertex2f(tp1x, tp1y);
	glVertex2f(tp2x, tp2y);
	glEnd();
	glPopMatrix();
	
	// Draw linia fins objecte 43
	if ((xi!=-1)&&(yi!=-1)){ 
		glColor3f(1.0, 1.0, 1.0);
		glPushMatrix();
		glLoadIdentity();
		glBegin(GL_LINES);
		glVertex2f(tp1x, tp1y);
		glVertex2f(xi, yi);
		glEnd();
		glPopMatrix();
	}
	
	// Draw punt invers
	if ((xi!=-1)&&(yi!=-1)){
		glColor3f(1.0, 1.0, 1.0);
		glPushMatrix();
		glTranslatef(xii, yii, 0.0f);
		glBegin(GL_LINE_LOOP);
		for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
			glVertex2d(cos(a) * 0.015, sin(a) * 0.015);
		}
		glEnd();
		glPopMatrix();
	}
	*/ 
}


void TuioDemo::drawTextInfo(float x, float y, double m[16], int ditpos){

	char mat[200];
	
	glColor3f(1.0, 1.0, 1.0);
	glPushMatrix();
	
	// Matriu
	glRasterPos2f(x,y+0.1);
	sprintf(mat,"%.2f    %.2f    %.2f    %.2f",m[0],m[1],m[2],m[3]);drawString(mat);
	glRasterPos2f(x,y+0.08);
	sprintf(mat,"%.2f    %.2f    %.2f    %.2f",m[4],m[5],m[6],m[7]);drawString(mat);
	glRasterPos2f(x,y+0.06);
	sprintf(mat,"%.2f    %.2f    %.2f    %.2f",m[8],m[9],m[10],m[11]);drawString(mat);
	glRasterPos2f(x,y+0.04);
	sprintf(mat,"%.2f    %.2f    %.2f    %.2f",m[12],m[13],m[14],m[15]);drawString(mat);

	glPopMatrix();
}


void TuioDemo::drawObjects(){	
	char id[3];
	std::list<TuioCursor*> cursorList = tuioClient->getTuioCursors();
	std::list<TuioObject*> objectList = tuioClient->getTuioObjects();
	
   	//draw black background	
	glPushMatrix();
    glColor3ub(0,0,0);
    glBegin(GL_QUADS);
	glVertex2f(0,0);
	glVertex2f(1,0);
	glVertex2f(1,1);
	glVertex2f(0,1);
    glEnd();
    glPopMatrix();
	
	/*
	// draw mapamundifons
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, mapaID);//
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glColor3ub(50,50,50);
	glBegin(GL_QUADS);
	glTexCoord2f(0,0);
	glVertex2f(0,0);
	glTexCoord2f(1,0);
	glVertex2f(1,0);
	glTexCoord2f(1,1);
	glVertex2f(1,1);
	glTexCoord2f(0,1);
	glVertex2f(0,1);
    glEnd();
	glDisable(GL_TEXTURE_2D);
	*/
		
	// Draw mapa mundi transformable
	drawMapaMundi();
	
	
	// draw cursors
	for (std::list<TuioCursor*>::iterator tuioCursor = cursorList.begin(); tuioCursor!=cursorList.end(); tuioCursor++) {
		std::list<TuioPoint> path = (*tuioCursor)->getPath(); // Obtenim el path de cada cursor
	
		if (path.size()>0) {
			
		
			// Pintar recorregut Path
			TuioPoint last_point = path.front();
			//glBegin(GL_LINES);
			//glColor3f(1.0, 0.0, 0.0);
			for (std::list<TuioPoint>::iterator point = path.begin(); point!=path.end(); point++) {

				//glVertex3f(last_point.getX(), last_point.getY(), 0.0f);
				//glVertex3f(point->getX(), point->getY(), 0.0f);
				last_point.update(point->getX(),point->getY());
								
			} //glEnd();
			 
			 
			// draw the finger tip
			glColor3f(1.0, 0, 0);
			glPushMatrix();
			glTranslatef(last_point.getX(), last_point.getY(), 0.0);
			glBegin(GL_TRIANGLE_FAN);
			for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
				glVertex2d(cos(a) * 0.01f, sin(a) * 0.01f);
			}
			glEnd();
			glPopMatrix();
			
			glColor3f(1.0, 1.0, 1.0);
			glRasterPos2f((*tuioCursor)->getX()-0.0025,(*tuioCursor)->getY()-0.005);
			sprintf(id,"%d",(*tuioCursor)->getFingerID());
			drawString(id);
		} 
	}
	
	/*
	// draw link entre dits
	if ((dit1_id!=-1)&&(dit2_id!=-1)){
		glColor3f(1.0, 1.0, 1.0);
		glPushMatrix();
		glBegin(GL_LINES);
		glVertex2d(dit1_x,dit1_y);
		glVertex2d(dit2_x,dit2_y);
		glEnd();
		glPopMatrix();
	}
	*/
	
	// draw dit 1 (verd)
	if (dit1_id!=-1){
		glColor3f(0.0, 1.0, 0.0); // DIT1 = VERD
		glPushMatrix();
		glLoadIdentity();
		glTranslatef(dit1_x, dit1_y, 0.0);
		glBegin(GL_TRIANGLE_FAN);
		for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
			glVertex2d(cos(a) * 0.01f, sin(a) * 0.01f);
		}
		glEnd();
		glBegin(GL_LINE_LOOP);
		for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
			glVertex2d(cos(a) * 0.015f, sin(a) * 0.015f);
		}
		glEnd();
		glPopMatrix();	
	}
	
	// draw dit 2 (blau)
	if (dit2_id!=-1){
		glColor3f(0.0, 0.0, 1.0);
		glPushMatrix();
		glLoadIdentity();
		glTranslatef(dit2_x, dit2_y, 0.0);
		glBegin(GL_TRIANGLE_FAN);
		for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
			glVertex2d(cos(a) * 0.01f, sin(a) * 0.01f);
		}
		glEnd();
		glBegin(GL_LINE_LOOP);
		for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
			glVertex2d(cos(a) * 0.015f, sin(a) * 0.015f);
		}
		glEnd();
		glPopMatrix();
	}
	
	// draw the objects
	for (std::list<TuioObject*>::iterator tuioObject = objectList.begin(); tuioObject!=objectList.end(); tuioObject++) {

		if ((*tuioObject)->getFiducialID()!=43){
			glColor3f(1.0, 0.0, 0.0);
			glPushMatrix();
			glTranslatef((*tuioObject)->getX(), (*tuioObject)->getY(), 0.0);
			glRotatef((*tuioObject)->getAngle()/M_PI*180, 0.0, 0.0, 1.0);
			glBegin(GL_QUADS);
				glVertex2f(-0.05f, -0.05f);
				glVertex2f(-0.05f, 0.05f);
				glVertex2f(0.05f, 0.05f);
				glVertex2f(0.05f, -0.05f);
			glEnd();
			glPopMatrix();

			glColor3f(1.0, 1.0, 1.0);
			glRasterPos2f((*tuioObject)->getX(),(*tuioObject)->getY());
			sprintf(id,"%d",(*tuioObject)->getFiducialID());
			drawString(id);	
		}else if((*tuioObject)->getFiducialID()==43){
			
			detectaPais(); // Comprova a quin païs es troba el punt
			
			// Quadrat
			glColor3f(0.3, 0.0, 0.0);
			if(Mix_Playing(1)) // Si sona algo mostra el volum més clar
				glColor3f(1.0, 0.0, 0.0);
			
			glPushMatrix();
			glTranslatef((*tuioObject)->getX(), (*tuioObject)->getY(), 0.0);
			glRotatef((*tuioObject)->getAngle()/M_PI*180, 0.0, 0.0, 1.0);
			glBegin(GL_TRIANGLE_FAN);
			float r=0.02f;
			for(double a = 0.0f; a <= 2*M_PI; a += 0.2f) {
				glVertex2d(cos(a) * r, sin(a) * r);
			}
			glEnd();
			glPopMatrix();
			
			// Anell
			glPushMatrix();
			glTranslatef((*tuioObject)->getX(), (*tuioObject)->getY(), 0.0);
			glBegin(GL_QUADS);
			float rad1,rad2;
			rad1=r;
			rad2=rad1+0.02f;
			double maxd;
			maxd=(M_PI*2)*(double)volume/128.0f;
			for(double a = 0.1f; a < maxd; a += 0.2f) {
				glVertex2d(cos(a) * rad1, sin(a) * rad1);
				glVertex2d(cos(a+0.1f) * rad1, sin(a+0.1f) * rad1);
				glVertex2d(cos(a+0.1f) * rad2, sin(a+0.1f) * rad2);
				glVertex2d(cos(a) * rad2, sin(a) * rad2);

			}			
			glEnd();
			glPopMatrix();
		}
	}

	// draw text info
	//drawTextInfo(0.04,0.04,modelview,1);
	
}


void TuioDemo::drawString(char* str){
	if (str && strlen(str)) {
		while (*str) {
			glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, *str);
			str++;
		}
	}
}


void TuioDemo::Init(){
	///
    /// Còdi que s'executarà al iniciar els gràfics
    ///
	// Carregar textures
	Image* image = loadBMP("image/mapa_petit3.bmp");
	mapaID = loadTexture(image);
	delete image;
	
	glPushMatrix(); // Inicialitzem matrius a IDENTITAT
	glLoadIdentity();
	glGetDoublev(GL_MODELVIEW_MATRIX , modelview); // Guardem la nova transformació
	glGetDoublev(GL_MODELVIEW_MATRIX , alt_modelview); // Guardem la nova transformació
	alt_modelview[12]=1.0f;
	alt_modelview[13]=1.0f;
	glPopMatrix();
	
	//load audio samples
	sampleNA=Mix_LoadWAV("sound/All_men_are_equal.wav");
	if(!sampleNA) {
		printf("Mix_LoadWAV: %s\n", Mix_GetError());
	}
	sampleSA=Mix_LoadWAV("sound/percloop_07.wav");
	if(!sampleSA) {
		printf("Mix_LoadWAV: %s\n", Mix_GetError());
	}
	sampleAF=Mix_LoadWAV("sound/ReDub.wav");
	if(!sampleAF) {
		printf("Mix_LoadWAV: %s\n", Mix_GetError());
	}
	sampleEU=Mix_LoadWAV("sound/violin.wav");
	if(!sampleEU) {
		printf("Mix_LoadWAV: %s\n", Mix_GetError());
	}
	
	
	Mix_AllocateChannels(2);
	
}


GLuint TuioDemo::loadTexture(Image* image) {
	GLuint textureId;
	glGenTextures(1, &textureId); //Make room for our texture
	glBindTexture(GL_TEXTURE_2D, textureId); //Tell OpenGL which texture to edit
	//Map the image to the texture
	glTexImage2D(GL_TEXTURE_2D,                //Always GL_TEXTURE_2D
				 0,                            //0 for now
				 GL_RGB,                       //Format OpenGL uses for image
				 image->width, image->height,  //Width and height
				 0,                            //The border of the image
				 GL_RGB, //GL_RGB, because pixels are stored in RGB format
				 GL_UNSIGNED_BYTE, //GL_UNSIGNED_BYTE, because pixels are stored
				 //as unsigned numbers
				 image->pixels);               //The actual pixel data
	return textureId; //Returns the id of the texture
}

